/**
 * TetisDB
 *
 * Implementação padrão de TetisContainer
 */
package br.com.tetisdb.container;

import br.com.tetisdb.lang.TetisObject;
import br.com.tetisdb.util.TetisContainerLock;
import java.io.File;
import java.io.IOException;

import br.com.tetisdb.configure.TConfigureContainer;
import br.com.tetisdb.configure.TetisConfigureContainer;
import br.com.tetisdb.domain.TDomain;
import br.com.tetisdb.domain.TetisDomain;
import br.com.tetisdb.io.IOManager;
import br.com.tetisdb.lang.TetisHashMap;
import java.util.ArrayList;
import java.util.List;

public class TContainer extends TetisObject implements TetisContainer {
   /*
    * contem todos os dominios iniciados por esse container. usa generics para
    * garantir que não vai haver outro tipo de dado.
    *
    * no key do hash contem o nome do dominio ("tetis.com.br") e o tetisdomain
    * referente dominio
    */
    private TetisHashMap<String, TetisDomain> domains = new TetisHashMap<String, TetisDomain>();
    
    /**
     * Configure do container
     */
    private TetisConfigureContainer configure;
    
    /**
     * Construtor padrão.
     *
     * @param workspace de trabalho. Exemplo: "/tmp/db".
     */
    public TContainer(String workspace) {
        tetisLogger.debug("Tentando TetisContainer: "+workspace);
        
        try {
            if (!workspace.endsWith("TetisDB")) {
                workspace += File.separator + "TetisDB";
            }
            
            tetisLogger.debug("Workspace: "+workspace);
            tetisLogger.debug("Criando TConfigureContainer");
            
            configure = new TConfigureContainer(workspace);
            
            try {
                IOManager.createPath(getConfigure().getWorkSpace());
            } catch (IOException ioe) {
                tetisLogger.error("Falha ao criar path do TetisContainer("+this+"). Erro: " + ioe.getMessage(), ioe);
                System.exit(1);
            }
            
            if(!TetisContainerLock.isLocked(this)) {
                //travando container
                TetisContainerLock.lock(this);
            } else {
                throw new IOException("TetisContainer já esta em uso!");
            }
        } catch (IOException ex) {
            tetisLogger.error("Erro ao travar o TetisContainer. Erro: "+ex.getMessage());
            System.exit(1);
        }
    }
    
    /**
     * Retorna a lista de domains desse TetisContainer
     *
     * @return Retorna a lista que contém todos os dominios desse container.
     */
    public TetisHashMap<String, TetisDomain> getDomains() {
        return domains;
    }
    
    /**
     * Retorna a Workspace.
     *
     * @return Retorna a Workspace do TetisContainer.
     */
    public String getWorkSpace() {
        return getConfigure().getWorkSpace();
    }
    
    /**
     * Cria/abre um dominio para esse TetisContainer.
     *
     * @param domain Nome do TetisDomain a ser criado
     */
    public TetisDomain getDomain(String domain) {
        if(domain == null) {
            return null;
        }
        
        if (!domains.exist(domain)) {
            try {
                TetisDomain td = new TDomain(domain, getConfigure().getWorkSpace());
                domains.put(domain, td); // grava o dominio criado no hashMap
                
                return td;
            } catch (IOException ex) {
                tetisLogger.error("Erro ao criar dominio: "+domain, ex);
            }
            
            return null;
        } else {
            return (TetisDomain) domains.get(domain);
        }
    }
    
    /**
     * Fecha do TetisContainer
     */
    public void close() {
        tetisLogger.info("Fechando TetisContainer...");
        
        List<TetisDomain> domains = new ArrayList(getDomains().values());
        
        for(TetisDomain domain : domains) {
            if(domain != null) {
                domain.close();
            }
        }
        
        TetisContainerLock.unlock(this);
        tetisLogger.info("TetisContainer fechado!");
    }
    
    /**
     * Retorna a configuracao do container
     *
     * @param TetisConfigureContainer Configuracao
     */
    public TetisConfigureContainer getConfigure() {
        return configure;
    }
}